Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR restructures the project for npm publishing as reactoscope, supporting both a Vite plugin (observatory()) and a standalone CLI (reactoscope) while splitting builds for the UI and render entry.
Changes:
- Introduces a packaged plugin entry (
src/plugin/index.ts) plus UI-serving and dev-server middleware to mount the Observatory at/__observatory. - Adds new UI capabilities (timeline/scenarios/pinned variants + pixel-diff modal + AI panel) and moves shared logic/constants into
src/shared/. - Updates packaging/build/publish pipeline (tsdown config, multi-vite build configs, npm metadata, CLI, and GitHub publish workflow).
Show a summary per file
| File | Description |
|---|---|
| vite.config.ui.ts | New Vite build config to output the packaged Observatory UI into dist/client. |
| vite.config.ts | Switches dev config to consume the packaged plugin array via observatory(). |
| vite.config.render.ts | New Vite library build for the iframe render entry (dist/render). |
| tsdown.config.ts | New tsdown build configuration for plugin outputs in dist/. |
| tsconfig.node.json | Adds new build config files to the TS “node” project includes. |
| src/ui/ViewportControls.tsx | Updates imports to use shared health types. |
| src/ui/VariantCard.tsx | New UI card for pinned variants rendering into iframes. |
| src/ui/useTimeline.ts | New hook providing timeline navigation/marking/replay with timer management. |
| src/ui/useTimeline.test.ts | Tests for timeline hook behaviors (branching, replay, cancellation). |
| src/ui/useStress.ts | Updates shared imports for stress/health and constants. |
| src/ui/useScenarios.ts | New hook to manage named scenario step sequences. |
| src/ui/useScenarios.test.ts | Tests for scenario CRUD + selection behavior. |
| src/ui/usePinnedVariants.ts | Switches UNSET sentinel import to shared constants. |
| src/ui/usePinnedVariants.test.ts | Updates component path used for storage key in tests. |
| src/ui/usePdiff.ts | Switches message constants import to shared constants. |
| src/ui/useAI.ts | Switches prop/stress types and constants to shared modules. |
| src/ui/timelineTree.ts | Switches UNSET import to shared constants. |
| src/ui/timelineTree.test.ts | Adds tests for timeline tree ops and marked-sequence traversal. |
| src/ui/TimelinePanel.tsx | New UI panel to display timeline tree and mark/replay/save actions. |
| src/ui/StressModal.tsx | Switches health analysis imports to shared module. |
| src/ui/ScenarioPanel.tsx | New UI panel for scenario playback controls + rename/delete + pdiff trigger. |
| src/ui/resolveProps.ts | Switches types/constants/hydration helper imports to shared modules. |
| src/ui/PropsPanel.tsx | Switches prop typing + UNSET import to shared modules. |
| src/ui/PdiffModal.tsx | New modal to navigate and view pixel diffs between step snapshots. |
| src/ui/pdiff.ts | New pixel-by-pixel ImageData comparator producing a magenta diff image. |
| src/ui/pdiff.test.ts | Tests for snapshot comparisons including size differences and alpha changes. |
| src/ui/HealthPanel.tsx | Switches health analysis imports to shared module. |
| src/ui/generateProps.ts | Switches prop typing and UNSET import to shared modules. |
| src/ui/ErrorBoundary.tsx | New error boundary for safer component rendering in the iframe/UI. |
| src/ui/ComponentRenderer.tsx | Switches to shared constants/types and adjusts dynamic import pathing. |
| src/ui/captureIframe.ts | Switches COMPONENT_ROOT_ID import to shared constants. |
| src/ui/buildIframeSrc.ts | Changes iframe base path to /__observatory for packaged routing. |
| src/ui/App.tsx | Switches shared imports + wires in new panels/features via shared constants/health. |
| src/ui/App.css | Large UI refresh + styles for new panels (timeline/scenarios/pdiff/AI). |
| src/ui/AIPanel.tsx | New AI panel UI for model selection, analysis, streaming chat, and controls. |
| src/shared/types.ts | New shared PropInfo type used by both plugin and UI. |
| src/shared/stressStats.ts | New shared stats + trend utilities for stress analysis. |
| src/shared/stressStats.test.ts | Unit tests for stats and trend detection. |
| src/shared/hydrateDescriptor.ts | New shared descriptor hydration used by prop hydration. |
| src/shared/hydrateDescriptor.test.ts | Unit tests for descriptor detection and hydration behavior. |
| src/shared/constants.ts | Adds shared UNSET sentinel to consolidate UI/plugin usage. |
| src/shared/analyzeHealth.ts | New shared health analysis (determinism/output growth/memory/speed/size). |
| src/shared/analyzeHealth.test.ts | Unit tests validating health findings and severity aggregation. |
| src/sandbox/TestButton.tsx | Removes sandbox component (project restructuring). |
| src/sandbox/LeakyButton.tsx | Removes sandbox component (project restructuring). |
| src/renderEntry.tsx | New iframe render entry used by the packaged UI plugin. |
| src/plugin/uiPlugin.ts | New plugin to serve prebuilt UI and virtual render HTML under /__observatory. |
| src/plugin/stressRender.ts | New SSR rendering helper for stress testing. |
| src/plugin/stressPlugin.ts | Updates stress endpoint for packaged paths + rootRef-based path handling. |
| src/plugin/schemaPlugin.ts | Moves PropInfo to shared + rootRef + tsconfig discovery. |
| src/plugin/index.ts | New public observatory() plugin factory + options + rootRef plumbing. |
| src/plugin/hydrateProps.ts | Switches to shared types/constants/hydration logic. |
| src/plugin/hydrateProps.test.ts | Updates test imports to use shared types/constants. |
| src/plugin/findTsconfig.ts | New helper to pick tsconfig for TS analysis. |
| src/plugin/aiPlugin.ts | Adds configurable Ollama URL + rootRef path handling for component source injection. |
| src/main.tsx | Updates import paths to new src/ui/* layout. |
| README.md | Rebrands and documents npm usage (CLI + plugin) and new features. |
| package.json | Converts to publishable npm package: exports/bin/engines/build scripts. |
| package-lock.json | Lockfile updates to reflect new deps/peers and packaging changes. |
| LICENSE | Adds MIT license file for publishing. |
| index.html | Updates title branding. |
| bin/observe.js | Replaces spawn vite approach with createServer() CLI wrapper. |
| .nvmrc | Pins Node major version for dev/publish consistency. |
| .github/workflows/publish.yml | Adds release-triggered npm publish workflow with provenance. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (3)
src/plugin/aiPlugin.ts:76
readComponentSource's path containment check (relative(root, absPath)+startsWith('..')) can be bypassed on Windows whencomponentPathresolves to a different drive letter (e.g.D:\...), becausepath.relativereturns an absolute path likeD:\...that does not start with... Consider hardening by rejecting absolutecomponentPathinputs and/or checkingpath.isAbsolute(rel)(orrel.includes(':')on win32), or by verifyingabsPathstarts with the normalized root path + separator afterresolve/realpath.
src/plugin/schemaPlugin.ts:249- The project-root containment check uses
relative(root, absPath)and rejects onlyrel.startsWith('..') || rel.startsWith('/'). On Windows, ifabsPathis on a different drive,relativereturns an absolute path (e.g.D:\foo) which bypasses this check. Please add an additional guard (e.g.path.isAbsolute(rel)/rel.includes(':')on win32, or verifyabsPathbegins with the normalized root + path separator).
src/plugin/stressPlugin.ts:114 - The path validation (
relative(rootRef.root, absPath)+startsWith('..')) is not sufficient on Windows: whencomponentresolves to another drive,path.relativereturns an absolute path (e.g.D:\...) that does not start with.., allowing escape from the project root. Please add a check forpath.isAbsolute(rel)(or an equivalent cross-drive guard), or validate by comparing normalizedabsPathprefix againstrootRef.root+ separator.
- Files reviewed: 41/64 changed files
- Comments generated: 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Package reactoscope for npm publishing
Restructures the project so it can be published to npm as
reactoscope- usable both as a Vite plugin and a standalone CLI for any React + TypeScript project.